﻿using Assistant;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using YoucaiReader.Entities;

/**
 * 创建时间：2014/9/20 15:07:53
 * 作者：yong.blackcore
 * Email：itblackhole@outlook.com
 * QQ：50404503
 */
namespace YoucaiReader.Helper
{
    public class Typesetting
    {
        public static string specialC_1, specialC_2, specialC_3, specialC_4, specialC_5, specialC_6, specialC_7, specialC_8, specialC_9, specialC_10;
        public string readFileName;
        private static string readBuf;
        public static float npageHeight;
        public static int nreaderCount;
        public int nfontSize;
        public float nxSpace, nySpace;
        public int npageLineNum;
        public float dfontHeight, dfontChinaWidth, dtopSpace;
        public bool bStatus;

        static Typesetting()
        {
            Typesetting.specialC_1 = "";
            Typesetting.specialC_2 = "";
            Typesetting.specialC_3 = "";
            Typesetting.specialC_4 = "";
            Typesetting.specialC_5 = "\t";
            Typesetting.specialC_6 = "";
            Typesetting.specialC_7 = "";
            Typesetting.specialC_8 = "";
            Typesetting.specialC_9 = "\u2029";
            Typesetting.specialC_10 = "\r";
            //面板的内容高度
            //Typesetting.npageHeight = 760f;
            Typesetting.npageHeight = (int)Application.Current.Host.Content.ActualHeight - 65;// 135;// 700f;
            Typesetting.nreaderCount = 8192;
        }

        public Typesetting(string fileName)
        {
            this.readFileName = fileName;
            if (!InternalDefaultBook.IsInternalBook(this.readFileName))
            {
                IsolatedStorageFileStream isolatedStorageFileStream = App.QQReader_StorageFile.StorageFile.OpenFile(this.readFileName, FileMode.Open, FileAccess.ReadWrite);
                if (isolatedStorageFileStream == null)
                {
                    this.bStatus = false;
                }
                else
                {
                    using (StreamReader streamReader = new StreamReader(isolatedStorageFileStream))
                    {
                        string end = streamReader.ReadToEnd();
                        Typesetting.readBuf = end;
                        if (end.Length > 0)
                        {
                            this.bStatus = true;
                        }
                    }
                    isolatedStorageFileStream.Close();
                }
            }
            else
            {
                Typesetting.readBuf = FileUtility.ReadFile(string.Concat(this.readFileName, ".txt"));
                if (Typesetting.readBuf.Length > 0)
                {
                    this.bStatus = true;
                }
            }
            if (this.bStatus)
            {
                string[] specialC1 = new string[] { Typesetting.specialC_1, "|", Typesetting.specialC_2, "|", Typesetting.specialC_3, "|", Typesetting.specialC_4, "|", Typesetting.specialC_5, "|", Typesetting.specialC_6, "|", Typesetting.specialC_7, "|", Typesetting.specialC_8 };
                Regex regex = new Regex(string.Concat(specialC1));
                regex.Replace(Typesetting.readBuf, " ");
                //段落分隔符,\u2029;
                string str = Typesetting.readBuf.Replace('\r', '\n').Replace('\u2029', '\n').Replace("      ", "\u3000\u3000").Replace("    ", "\u3000\u3000").Replace("  ", "\u3000");
                int num = 0;
                while (str[num] == ' ' || str[num] == '\n' || str[num] == '\u3000')
                {
                    num++;
                }
                Typesetting.readBuf = str.Remove(0, num);
            }
        }

        public bool Calculate(PageInfo page, int bufIndex, int fontSize, PageDisplacement pd)
        {
            char[] chrArray;
            char i;
            int num = 0;
            if (!this.bStatus)
            {
                return false;
            }
            this.nySpace = (float)(fontSize / 2);
            this.nfontSize = fontSize;
            this.dfontHeight = this.getFontHeight();
            this.dfontChinaWidth = this.getFontWidth('\u4E2D');
            this.npageLineNum = this.getPageLineNum(Typesetting.npageHeight);
            this.dtopSpace = this.getTopSpace(Typesetting.npageHeight);
            float single = 460f % this.dfontChinaWidth;
            float single1 = 10f + single / 2f;
            float single2 = 460f - single;
            int num1 = 0;
            bool flag = false;
            string str = "";
            int num2 = 0;
            float single3 = 0f;
            float single4 = 0f;
            float single5 = this.dtopSpace;
            if (pd != PageDisplacement.Previous)
            {
                page.textIndex = bufIndex;
                if (bufIndex + Typesetting.nreaderCount <= Typesetting.readBuf.Length)
                {
                    chrArray = new char[Typesetting.nreaderCount];
                    Typesetting.readBuf.CopyTo(bufIndex, chrArray, 0, Typesetting.nreaderCount);
                }
                else
                {
                    chrArray = new char[Typesetting.readBuf.Length - bufIndex];
                    Typesetting.readBuf.CopyTo(bufIndex, chrArray, 0, Typesetting.readBuf.Length - bufIndex);
                }
            }
            else
            {
                if (bufIndex <= 0)
                {
                    return false;
                }
                int num3 = bufIndex;
                List<int> nums = new List<int>();
                bool flag1 = false;
                if (Typesetting.readBuf[bufIndex] != '\n')
                {
                    flag1 = true;
                }
                do
                {
                    flag = false;
                    int num4 = 0;
                    bool flag2 = false;
                    int num5 = 0;
                    int num6 = Typesetting.readBuf.LastIndexOf('\n', num3);
                    if (num6 < 0)
                    {
                        num6 = 0;
                        flag = true;
                    }
                    int num7 = 0;
                    if (!flag1)
                    {
                        num7 = num3 - num6 + 1;
                    }
                    else
                    {
                        num7 = num3 - num6;
                        flag1 = false;
                    }
                    if (num7 > 0)
                    {
                        char[] chrArray1 = new char[num7];
                        Typesetting.readBuf.CopyTo(num6, chrArray1, 0, num7);
                        single3 = 0f;
                        single4 = 0f;
                        single5 = this.dtopSpace;
                        do
                        {
                            single4 = single4 + single3;
                            int num8 = num5;
                            num5 = num8 + 1;
                            char chr = chrArray1[num8];
                            while (chr == '\n')
                            {
                                flag = true;
                                if (num5 != (int)chrArray1.Length)
                                {
                                    int num9 = num5;
                                    num5 = num9 + 1;
                                    chr = chrArray1[num9];
                                }
                                else
                                {
                                    flag2 = true;
                                    break;
                                }
                            }
                            if (flag2)
                            {
                                break;
                            }
                            single3 = (chr <= '\u007F' || this.specialChar(chr) ? this.getFontWidth(chr) : this.dfontChinaWidth);
                            if (single4 + single3 <= single2 && !flag)
                            {
                                continue;
                            }
                            nums.Insert(num4, num6 + num5 - 1);
                            num4++;
                            single4 = 0f;
                            flag = false;
                        }
                        while (num5 != (int)chrArray1.Length);
                    }
                    num3 = num6 - 1;
                }
                while (nums.Count <= this.npageLineNum && num3 > 0);
                num3 = (nums.Count <= this.npageLineNum ? nums[0] : nums[nums.Count - this.npageLineNum]);
                page.textIndex = num3;
                chrArray = new char[bufIndex - num3];
                Typesetting.readBuf.CopyTo(num3, chrArray, 0, bufIndex - num3);
                flag = false;
                single3 = 0f;
                single4 = 0f;
                single5 = this.dtopSpace;
            }
            if ((int)chrArray.Length <= 0)
            {
                return false;
            }
            do
            {
                single4 = single4 + single3;
                PageInfo _pageInfo = page;
                int num10 = _pageInfo.textCount;
                int num11 = num10;
                _pageInfo.textCount = num10 + 1;
                for (i = chrArray[num11]; i == '\n'; i = chrArray[num])
                {
                    flag = true;
                    if ((int)chrArray.Length == page.textCount)
                    {
                        if (str.Length > 0)
                        {
                            page.textContent.Add(str);
                        }
                        return true;
                    }
                    PageInfo _pageInfo1 = page;
                    int num12 = _pageInfo1.textCount;
                    num = num12;
                    _pageInfo1.textCount = num12 + 1;
                }
                single3 = (i <= '\u007F' || this.specialChar(i) ? this.getFontWidth(i) : this.dfontChinaWidth);
                if (single4 + single3 > single2 || flag)
                {
                    if (num2 == 1 && str.Length > 0)
                    {
                        page.textContent.Add(str);
                        num2 = 0;
                        str = "";
                    }
                    int num13 = num1 + 1;
                    num1 = num13;
                    if (num13 == this.npageLineNum)
                    {
                        PageInfo _pageInfo2 = page;
                        _pageInfo2.textCount = _pageInfo2.textCount - 1;
                        return true;
                    }
                    single4 = 0f;
                    single5 = single5 + (this.nySpace + this.dfontHeight);
                    flag = false;
                }
                if (i <= '\u007F' || this.specialChar(i))
                {
                    if (num2 == 1 && str.Length > 0)
                    {
                        page.textContent.Add(str);
                        str = "";
                    }
                    num2 = 2;
                    page.textContentX.Add(single4 + single1);
                    page.textContentY.Add(single5);
                    page.textContent.Add(new string(i, 1));
                }
                else
                {
                    if (num2 != 1)
                    {
                        page.textContentX.Add(single4 + single1);
                        page.textContentY.Add(single5);
                    }
                    str = string.Concat(str, new string(i, 1));
                    num2 = 1;
                }
                if ((int)chrArray.Length != page.textCount)
                {
                    continue;
                }
                if (str.Length > 0)
                {
                    page.textContent.Add(str);
                }
                return true;
            }
            while ((int)chrArray.Length != page.textCount);
            return true;
        }

        public float CalculateChar(char c)
        {
            if (this.specialChar(c))
            {
                return this.getFontWidth(c);
            }
            if (c > '\u007F' || c == '\"')
            {
                return this.dfontChinaWidth;
            }
            return this.getFontWidth(c);
        }

        public static string getBookBuf()
        {
            return Typesetting.readBuf;
        }

        public int getBookLength()
        {
            return Typesetting.readBuf.Length;
        }

        public float getFontHeight()
        {
            TextBlock textBlock = new TextBlock();
            string str = new string('\u4E2D', 1);
            textBlock.FontSize = (double)this.nfontSize;
            textBlock.Text = str;
            return (float)textBlock.ActualHeight;
        }

        public float getFontWidth(char c)
        {
            TextBlock textBlock = new TextBlock();
            string str = new string(c, 1);
            textBlock.FontSize = (double)this.nfontSize;
            textBlock.Text = str;
            return (float)textBlock.ActualWidth;
        }

        public float getFontWidth(string str)
        {
            TextBlock textBlock = new TextBlock()
            {
                Text = str,
                FontSize = (double)this.nfontSize
            };
            return (float)textBlock.ActualWidth;
        }

        public int getPageLineNum(float maxHeight)
        {
            return (int)(maxHeight / (this.dfontHeight + this.nySpace));
        }

        public float getTopSpace(float maxHeight)
        {
            return 20f + maxHeight % (this.dfontHeight + this.nySpace) / 2f;
        }

        public bool specialChar(char c)
        {
            if (c == '！' || c == '\'' || c == '“' || c == '”' || c == '’' || c == '‘')
            {
                return true;
            }
            return c == '…';
        }
    }
}
